package com.cw.lang.common.utils;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
/**
 * 雪花算法流水号生成工具
 *
 * @author zhanghq23531
 * @version FleName:  SequenceTool .java  v0.1  2018/10/12 11:40 Exp $
 */
public class SequenceTool {


    private static Sequence sequence = null;

    // 机器标识位数
    private final static long workerIdBits = 5L;

    // 数据中心标识位数
    private final static long datacenterIdBits = 5L;

    static {
        new SequenceTool();
    }
    public static synchronized Long nextLongId() {
        return sequence.nextId();
    }
    public static synchronized String nextId() {
        return String.valueOf(sequence.nextId());
    }


    private SequenceTool() {

        //获取机器编码
        long workerId = this.getMachineNum();
        //获取进程编码
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        long processId = Long.valueOf(runtimeMXBean.getName().split("@")[0]);

        //避免编码超出最大值
        //服务器掩码
        long workerMask = ~(-1L << workerIdBits);
        workerId = workerId & workerMask;
        //进程掩码
        long processMask = ~(-1L << datacenterIdBits);
        processId = processId & processMask;
        sequence = new Sequence(workerId, processId);
    }


    /**
     * 获取机器编码
     *
     * @return machinePiece
     */
    private long getMachineNum() {
        long machinePiece;
        StringBuilder sb = new StringBuilder();
        Enumeration<NetworkInterface> e = null;
        try {
            e = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e1) {
            e1.printStackTrace();
        }
        while (e.hasMoreElements()) {
            NetworkInterface ni = e.nextElement();
            sb.append(ni.toString());
        }
        machinePiece = sb.toString().hashCode();
        return machinePiece;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 1000000; i++) {
            System.out.println(SequenceTool.nextId());
        }
    }
}


